Learn in 10 minutes

Learn in 10 minutes

10분 안에 C 배우기

Programming Language

C는 효율성과 하드웨어에 가까운 기능으로 유명한 강력한 범용 프로그래밍 언어입니다. 이 튜토리얼은 C 프로그래밍의 기초를 다루며 언어를 빠르게 이해할 수 있도록 도와줍니다.

1. 첫 번째 C 프로그램 작성하기

클래식한 “Hello, World!” 프로그램부터 시작해보겠습니다. hello.c라는 파일을 생성하고 다음 코드를 입력하세요:

#include <stdio.h>

int main() {
    printf("Hello, World!\n");
    return 0;
}

파일을 저장하고 GCC 같은 C 컴파일러를 사용하여 컴파일하세요:

gcc hello.c -o hello
./hello

출력 결과는 다음과 같습니다:

Hello, World!

이 간단한 프로그램은 C의 기본 구조를 보여줍니다:

  • #include <stdio.h>는 표준 입출력 라이브러리를 포함합니다
  • int main()은 프로그램의 진입점입니다
  • printf()는 텍스트 출력을 표시합니다
  • return 0은 성공적인 실행을 나타냅니다

2. 기본 문법

C는 구조화된 문법을 사용하며 세미콜론으로 문장을 종료하고 중괄호 {}로 코드 블록을 정의합니다.

// 이것은 한 줄 주석입니다
/* 이것은 여러 줄 주석입니다 */

#include <stdio.h>

int main() {
    printf("Hello, World!\n");
    return 0;
}

C의 기본 문법 규칙:

  • 세미콜론: 모든 문장은 세미콜론 ;으로 끝나야 합니다
  • 주석: 한 줄 주석은 //를 사용하고, 여러 줄 주석은 /* */를 사용합니다
  • 코드 블록: 중괄호 {}로 정의됩니다
  • 대소문자 구분: C는 대소문자를 구분합니다 (main vs Main)

3. 변수와 데이터 타입

C는 정적 타입 언어로, 사용하기 전에 변수 타입을 선언해야 합니다.

기본 변수 명명 규칙:

  • 변수 이름은 문자, 숫자, 밑줄을 포함할 수 있습니다
  • 변수 이름은 숫자로 시작할 수 없습니다
  • 변수 이름은 대소문자를 구분합니다
  • C 키워드는 변수 이름으로 사용할 수 없습니다

C의 주요 데이터 타입:

  • int: 정수 (예: 42, -10)
  • float: 부동 소수점 숫자 (예: 3.14, -2.5)
  • double: 배정밀도 부동 소수점 숫자
  • char: 단일 문자 (예: 'A', 'z')
  • void: 타입 없음
int age = 25;
float temperature = 36.5;
double pi = 3.14159265359;
char grade = 'A';

3.1 정수 타입

C는 다양한 크기의 여러 정수 타입을 제공합니다:

char small_number = 100;        // 보통 1바이트
short medium_number = 32000;    // 보통 2바이트
int regular_number = 1000000;   // 보통 4바이트
long large_number = 1000000000; // 보통 4 또는 8바이트

3.2 부동 소수점 타입

float single_precision = 3.14f;
double double_precision = 3.14159265359;
long double extended_precision = 3.14159265358979323846L;

3.3 문자 타입

문자는 ASCII 인코딩을 사용하여 정수로 저장됩니다:

char letter = 'A';
char digit = '7';
char newline = '\n';
char tab = '\t';

4. 상수

상수는 프로그램 실행 중에 변경할 수 없는 고정된 값입니다:

const int MAX_SIZE = 100;
const float PI = 3.14159;
const char NEWLINE = '\n';

#define MAX_USERS 1000
#define PI 3.14159

5. 입력과 출력

C는 입력과 출력 작업을 위해 stdio.h의 함수들을 사용합니다.

5.1 printf()로 출력하기

#include <stdio.h>

int main() {
    int age = 25;
    float height = 1.75;
    char name[] = "John";

    printf("Hello, %s!\n", name);
    printf("You are %d years old\n", age);
    printf("Your height is %.2f meters\n", height);

    return 0;
}

일반적인 형식 지정자:

  • %d - 정수
  • %f - float/double
  • %c - 문자
  • %s - 문자열
  • %p - 포인터

5.2 scanf()로 입력받기

#include <stdio.h>

int main() {
    int age;
    float height;
    char name[50];

    printf("Enter your name: ");
    scanf("%s", name);

    printf("Enter your age: ");
    scanf("%d", &age);

    printf("Enter your height: ");
    scanf("%f", &height);

    printf("Hello %s, you are %d years old and %.2f meters tall\n",
           name, age, height);

    return 0;
}

6. 연산자

C는 다양한 계산을 위한 풍부한 연산자 집합을 제공합니다.

6.1 산술 연산자

int a = 10, b = 3;

printf("Addition: %d\n", a + b);      // 13
printf("Subtraction: %d\n", a - b);   // 7
printf("Multiplication: %d\n", a * b); // 30
printf("Division: %d\n", a / b);      // 3
printf("Modulus: %d\n", a % b);       // 1

6.2 비교 연산자

int x = 5, y = 10;

printf("Equal: %d\n", x == y);     // 0 (false)
printf("Not equal: %d\n", x != y); // 1 (true)
printf("Greater than: %d\n", x > y);  // 0
printf("Less than: %d\n", x < y);  // 1

6.3 논리 연산자

int a = 1, b = 0;

printf("AND: %d\n", a && b);  // 0
printf("OR: %d\n", a || b);   // 1
printf("NOT: %d\n", !a);      // 0

6.4 비트 연산자

unsigned int a = 5;  // 2진수로 0101
unsigned int b = 3;  // 2진수로 0011

printf("AND: %d\n", a & b);   // 1 (0001)
printf("OR: %d\n", a | b);    // 7 (0111)
printf("XOR: %d\n", a ^ b);   // 6 (0110)
printf("NOT: %d\n", ~a);      // 시스템에 따라 다름
printf("Left shift: %d\n", a << 1);  // 10 (1010)
printf("Right shift: %d\n", a >> 1); // 2 (0010)

7. 제어 흐름

C는 프로그램 실행을 관리하기 위한 여러 제어 흐름 문을 제공합니다.

7.1 if 문

int age = 20;

if (age >= 18) {
    printf("Adult\n");
} else if (age >= 13) {
    printf("Teen\n");
} else {
    printf("Child\n");
}

7.2 switch 문

int day = 3;

switch (day) {
    case 1:
        printf("Monday\n");
        break;
    case 2:
        printf("Tuesday\n");
        break;
    case 3:
        printf("Wednesday\n");
        break;
    default:
        printf("Other day\n");
}

7.3 for 루프

for (int i = 0; i < 5; i++) {
    printf("i = %d\n", i);
}

7.4 while 루프

int count = 0;
while (count < 5) {
    printf("Count: %d\n", count);
    count++;
}

7.5 do-while 루프

int count = 0;
do {
    printf("Count: %d\n", count);
    count++;
} while (count < 5);

7.6 break와 continue

for (int i = 0; i < 10; i++) {
    if (i == 5) {
        break;  // 루프 종료
    }
    if (i % 2 == 0) {
        continue;  // 짝수 건너뛰기
    }
    printf("i = %d\n", i);  // 출력: 1, 3
}

8. 배열

배열은 같은 타입의 여러 값을 저장합니다.

8.1 1차원 배열

int numbers[5] = {1, 2, 3, 4, 5};

// 요소 접근
printf("First element: %d\n", numbers[0]);
printf("Last element: %d\n", numbers[4]);

// 요소 수정
numbers[0] = 10;

// 배열 순회
for (int i = 0; i < 5; i++) {
    printf("numbers[%d] = %d\n", i, numbers[i]);
}

8.2 다차원 배열

int matrix[2][3] = {
    {1, 2, 3},
    {4, 5, 6}
};

// 요소 접근
printf("matrix[1][2] = %d\n", matrix[1][2]);  // 6

// 2차원 배열 순회
for (int i = 0; i < 2; i++) {
    for (int j = 0; j < 3; j++) {
        printf("%d ", matrix[i][j]);
    }
    printf("\n");
}

9. 문자열

C에서 문자열은 널 문자 \0로 종료되는 문자 배열입니다.

char greeting[] = "Hello";  // 자동으로 널 종결자 포함
char name[20] = "John";

// string.h의 문자열 함수
#include <string.h>

char str1[20] = "Hello";
char str2[20] = "World";

printf("Length: %lu\n", strlen(str1));  // 5
strcpy(str1, str2);  // str2를 str1에 복사
printf("After copy: %s\n", str1);  // World

if (strcmp(str1, str2) == 0) {
    printf("Strings are equal\n");
}

10. 함수

함수는 특정 작업을 수행하는 재사용 가능한 코드 블록입니다.

10.1 함수 정의와 호출

#include <stdio.h>

// 함수 선언
int add(int a, int b);

int main() {
    int result = add(5, 3);
    printf("5 + 3 = %d\n", result);
    return 0;
}

// 함수 정의
int add(int a, int b) {
    return a + b;
}

10.2 반환 값이 없는 함수

void greet(char name[]) {
    printf("Hello, %s!\n", name);
}

int main() {
    greet("Alice");
    return 0;
}

10.3 재귀 함수

int factorial(int n) {
    if (n <= 1) {
        return 1;
    }
    return n * factorial(n - 1);
}

int main() {
    printf("5! = %d\n", factorial(5));  // 120
    return 0;
}

11. 포인터

포인터는 메모리 주소를 저장하는 변수입니다.

11.1 기본 포인터 사용법

int number = 42;
int *ptr = &number;  // ptr은 number의 주소를 저장

printf("Value: %d\n", number);     // 42
printf("Address: %p\n", &number);  // 메모리 주소
printf("Pointer value: %d\n", *ptr); // 42 (역참조)

// 포인터를 통해 값 수정
*ptr = 100;
printf("New value: %d\n", number);  // 100

11.2 포인터와 배열

int numbers[] = {1, 2, 3, 4, 5};
int *ptr = numbers;  // 첫 번째 요소를 가리킴

printf("First element: %d\n", *ptr);        // 1
printf("Second element: %d\n", *(ptr + 1)); // 2

// 배열 이름은 기본적으로 첫 번째 요소를 가리키는 포인터입니다
for (int i = 0; i < 5; i++) {
    printf("numbers[%d] = %d\n", i, *(numbers + i));
}

11.3 포인터와 함수

void swap(int *a, int *b) {
    int temp = *a;
    *a = *b;
    *b = temp;
}

int main() {
    int x = 5, y = 10;
    printf("Before swap: x=%d, y=%d\n", x, y);
    swap(&x, &y);
    printf("After swap: x=%d, y=%d\n", x, y);
    return 0;
}

12. 구조체

구조체는 관련된 변수들을 함께 그룹화할 수 있게 해줍니다.

12.1 구조체 정의와 사용

#include <stdio.h>
#include <string.h>

// 구조체 정의
struct Student {
    char name[50];
    int age;
    float gpa;
};

int main() {
    // 구조체 변수 생성
    struct Student student1;

    // 값 할당
    strcpy(student1.name, "Alice");
    student1.age = 20;
    student1.gpa = 3.8;

    // 구조체 멤버 접근
    printf("Name: %s\n", student1.name);
    printf("Age: %d\n", student1.age);
    printf("GPA: %.2f\n", student1.gpa);

    return 0;
}

12.2 포인터와 구조체

struct Point {
    int x;
    int y;
};

int main() {
    struct Point p1 = {10, 20};
    struct Point *ptr = &p1;

    printf("Coordinates: (%d, %d)\n", ptr->x, ptr->y);

    return 0;
}

13. 동적 메모리 할당

C는 동적 메모리 관리를 위한 함수들을 제공합니다.

13.1 malloc, calloc, realloc, free

#include <stdio.h>
#include <stdlib.h>

int main() {
    // 5개의 정수를 위한 메모리 할당
    int *numbers = (int*)malloc(5 * sizeof(int));

    if (numbers == NULL) {
        printf("Memory allocation failed!\n");
        return 1;
    }

    // 배열 초기화
    for (int i = 0; i < 5; i++) {
        numbers[i] = i * 10;
    }

    // 배열 출력
    for (int i = 0; i < 5; i++) {
        printf("numbers[%d] = %d\n", i, numbers[i]);
    }

    // 할당된 메모리 해제
    free(numbers);

    return 0;
}

13.2 동적 문자열 할당

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int main() {
    char *name = (char*)malloc(50 * sizeof(char));

    if (name != NULL) {
        strcpy(name, "Dynamic string");
        printf("Name: %s\n", name);
        free(name);
    }

    return 0;
}

14. 파일 작업

C는 파일 읽기와 쓰기를 위한 함수들을 제공합니다.

14.1 파일에 쓰기

#include <stdio.h>

int main() {
    FILE *file = fopen("example.txt", "w");

    if (file == NULL) {
        printf("Error opening file!\n");
        return 1;
    }

    fprintf(file, "Hello, File!\n");
    fprintf(file, "This is a test.\n");

    fclose(file);
    printf("File written successfully.\n");

    return 0;
}

14.2 파일에서 읽기

#include <stdio.h>

int main() {
    FILE *file = fopen("example.txt", "r");

    if (file == NULL) {
        printf("Error opening file!\n");
        return 1;
    }

    char buffer[100];

    while (fgets(buffer, sizeof(buffer), file) != NULL) {
        printf("%s", buffer);
    }

    fclose(file);

    return 0;
}

15. 전처리기 지시문

전처리기 지시문은 컴파일 전에 처리됩니다.

15.1 #include

#include <stdio.h>    // 시스템 헤더 파일
#include "myheader.h" // 사용자 헤더 파일

15.2 #define

#define PI 3.14159
#define MAX(a, b) ((a) > (b) ? (a) : (b))

int main() {
    double area = PI * 5 * 5;
    int larger = MAX(10, 20);

    printf("Area: %.2f\n", area);
    printf("Larger number: %d\n", larger);

    return 0;
}

15.3 조건부 컴파일

#define DEBUG 1

int main() {
    #ifdef DEBUG
        printf("Debug mode enabled\n");
    #endif

    #if DEBUG == 1
        printf("Debug level 1\n");
    #elif DEBUG == 2
        printf("Debug level 2\n");
    #else
        printf("No debug\n");
    #endif

    return 0;
}

16. 오류 처리

C는 내장된 예외 처리가 없으므로 반환 값과 오류 코드를 사용합니다.

#include <stdio.h>
#include <errno.h>
#include <string.h>

int main() {
    FILE *file = fopen("nonexistent.txt", "r");

    if (file == NULL) {
        printf("Error opening file: %s\n", strerror(errno));
        return 1;
    }

    fclose(file);
    return 0;
}

이 포괄적인 C 튜토리얼은 C 프로그래밍을 시작하는 데 필요한 필수 개념들을 다룹니다. 이 예제들을 연습하고 언어에 더 익숙해지면 연결 리스트, 함수 포인터, 다중 파일 프로그램과 같은 더 고급 주제들을 탐구해보세요.